package com.googlecode.dgwt.client.dijit.view.store;

import com.googlecode.dgwt.client.dijit.view.base.FocusViewBase;
import com.googlecode.dgwt.client.dojo.Dojo;
import com.googlecode.dgwt.client.dojo.data.base.ModeledStore;
import com.googlecode.dgwt.client.dojo.data.base.Store;
import com.googlecode.dgwt.client.dojo.data.listener.AttachListener;
import com.googlecode.dgwt.client.dojo.data.listener.DataListener;
import com.googlecode.dgwt.client.dojo.data.listener.ModelListener;
import com.googlecode.dgwt.client.dojo.data.listener.StoreListener;
import com.googlecode.dgwt.client.dojo.exception.AttachException;
import com.googlecode.dgwt.client.dojo.exception.DojoRuntimeException;

/**
 * Base class for views that works with a {@link Store}.
 * 
 * @author wellsantos@wellsantos.com
 * @since 0.01
 */
public abstract class StoreViewBase extends FocusViewBase implements StoreView, AttachListener<Store<Object>> {

    private Store<Object> store;

    protected StoreViewBase(boolean ready) {
        super(ready);
    }

    public void setStore(Store<Object> store){
        if (this.store != store){
            if (store == null){
                if (this.store != null){
                    this.store.removeListener(this);
                }
                this.store = null;
                return;
            }
            
            try {
                doAttach(store);
            } catch (AttachException e) {
                throw new DojoRuntimeException(e);
            }            
        }
    }
        
    public Store<Object> getStore(){
        assert (store != null) : Dojo.reflect.getSimpleName(getClass()) + ": no store attached";
        return store;
    }
    
    public boolean hasStore(){
        return store != null;
    }
    
    public boolean hasStore(Store<?> store){
        return this.store != null && this.store.equals(store);
    }
    

    // Implements AttachListener
    
    
    @Override
    public final void onAttach(Store<Object> parent) throws AttachException {
    }

    @Override
    public final void onDetach(Store<Object> parent) {
        if (hasStore(parent)){
            doDetach(store);
        }
    }
    
    protected void doAttach(Store<Object> store) throws AttachException {
        if (this.store != null){
            this.store.removeListener(this);
        }        

        this.store = store;
        
        if (this.store instanceof ModeledStore<?>){
            ModeledStore<Object> modeledStore = ((ModeledStore<Object>)this.store);
            modeledStore.registerParent(this);
            
            if ((Object)this instanceof StoreListener<?>){
                modeledStore.addListener((StoreListener<Object>)(AttachListener<Store<Object>>)this);
            }
            else if ((Object)this instanceof ModelListener<?>){ 
                modeledStore.addListener((ModelListener<Object>)(AttachListener<Store<Object>>)this);
            }
        }
        else if ((Object)this instanceof DataListener<?>){
            this.store.addListener((DataListener<Object>)(AttachListener<Store<Object>>)this);
        }
    }

    protected void doDetach(Store<Object> parent) {
        this.store = null;
    }
    
}
